`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    02:34:21 02/24/2012 
// Design Name: 
// Module Name:    pcie_axi_bridge 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module MasterBridge(
  input           CLK,
  input           RST,
  
  input           S_TVALID,
  output          S_TREADY,
  input   [127:0] S_TDATA,
  input   [3:0]   S_TSTRB,
  input           S_TLAST,
  output          M_TVALID,
  input           M_TREADY,
  output  [127:0] M_TDATA,
  output  [3:0]   M_TSTRB,
  output          M_TLAST,
  
  output  [31:0]  M_AWADDR,
  output  [7:0]   M_AWLEN,
  output          M_AWVALID,
  input           M_AWREADY,
  output  [31:0]  M_WDATA,
  output  [3:0]   M_WSTRB,
  output          M_WVALID,
  input           M_WREADY,
  input   [1:0]   M_BRESP,
  input           M_BVALID,
  output          M_BREADY,
  output  [31:0]  M_ARADDR,
  output          M_ARVALID,
  input           M_ARREADY,
  input   [31:0]  M_RDATA,
  input   [1:0]   M_RRESP,
  input           M_RVALID,
  output          M_RREADY
  );

  wire        wr_tvalid;
  wire        wr_tready;
  wire        rd_tvalid;
  wire        rd_tready;
  
  MasterBridgeWr
  mm_wr(
    .CLK          (CLK),
    .RST          (RST),
    
    .S_TVALID     (wr_tvalid),
    .S_TREADY     (wr_tready),
    .S_TDATA      (S_TDATA ),
    .S_TSTRB      (S_TSTRB ),
    .S_TLAST      (S_TLAST ),
  
    .M_AWADDR     (M_AWADDR ),
    .M_AWLEN      (M_AWLEN),
    .M_AWVALID    (M_AWVALID),
    .M_AWREADY    (M_AWREADY),
    .M_WDATA      (M_WDATA  ),
    .M_WSTRB      (M_WSTRB  ),
    .M_WVALID     (M_WVALID ),
    .M_WREADY     (M_WREADY ),
    .M_BRESP      (M_BRESP  ),
    .M_BVALID     (M_BVALID ),
    .M_BREADY     (M_BREADY )
  );
  
  MasterBridgeRd
  mm_rd(
    .CLK          (CLK),
    .RST          (RST),
    
    .S_TVALID     (rd_tvalid),
    .S_TREADY     (rd_tready),
    .S_TDATA      (S_TDATA ),
    .S_TSTRB      (S_TSTRB ),
    .S_TLAST      (S_TLAST ),
    .M_TVALID     (M_TVALID),
    .M_TREADY     (M_TREADY),
    .M_TDATA      (M_TDATA ),
    .M_TSTRB      (M_TSTRB ),
    .M_TLAST      (M_TLAST ),
  
    .M_ARADDR     (M_ARADDR ),
    .M_ARVALID    (M_ARVALID),
    .M_ARREADY    (M_ARREADY),
    .M_RDATA      (M_RDATA  ),
    .M_RRESP      (M_RRESP  ),
    .M_RVALID     (M_RVALID ),
    .M_RREADY     (M_RREADY )
  );

  rd_wr_dmux demux(
    .CLK        (CLK),
    .RST        (RST),
    
    .S_TVALID   (S_TVALID),
    .S_TREADY   (S_TREADY),
    .S_TDATA    (S_TDATA ),
    .S_TLAST    (S_TLAST ),
    
    .RD_TVALID  (rd_tvalid),
    .RD_TREADY  (rd_tready),
    .WR_TVALID  (wr_tvalid),
    .WR_TREADY  (wr_tready)
  );
  
endmodule

module rd_wr_dmux(
  input           CLK,
  input           RST,
  
  input           S_TVALID,
  output          S_TREADY,
  input   [127:0] S_TDATA,
  input           S_TLAST,
  
  output          RD_TVALID,
  input           RD_TREADY,
  output          WR_TVALID,
  input           WR_TREADY
);

  reg first_beat;
  always @(posedge CLK)
  begin
    if (RST || (S_TVALID && S_TREADY && S_TLAST))
      first_beat <= 1'b1;
    else if(S_TVALID && S_TREADY)
      first_beat <= 1'b0;
  end
  
  assign RD_TVALID = first_beat && !S_TDATA[30] && S_TVALID;
  assign WR_TVALID = (first_beat ? S_TDATA[30] : 1'b1) && S_TVALID;
  
  assign S_TREADY = RD_TVALID && RD_TREADY || WR_TVALID && WR_TREADY;
endmodule

module MasterBridgeWr(
  input           CLK,
  input           RST,
  
  input           S_TVALID,
  output          S_TREADY,
  input   [127:0] S_TDATA,
  input   [3:0]   S_TSTRB,
  input           S_TLAST,
  
  output  [31:0]  M_AWADDR,
  output  [7:0]   M_AWLEN,
  output          M_AWVALID,
  input           M_AWREADY,
  output  [31:0]  M_WDATA,
  output  [3:0]   M_WSTRB,
  output          M_WVALID,
  input           M_WREADY,
  input   [1:0]   M_BRESP,
  input           M_BVALID,
  output          M_BREADY
  );

  wire s32_tvalid;
  wire s32_tready = 1'b1;
  wire [31:0] s32_tdata;
  wire s32_tlast;
  
  reg [10:0]  beat_count;
  reg [9:0] rSLength;
  reg r4DWH;
  
  always @(posedge CLK)
  begin
    if (RST || s32_tvalid && s32_tlast)
      beat_count <= 0;
    else if (s32_tvalid && s32_tready)
      beat_count <= beat_count + 1;
  end
  
  always @(posedge CLK)
  begin
    if (s32_tvalid)
    begin
      case (beat_count)
        0:
        begin
          rSLength <= s32_tdata[9:0];
          r4DWH <= s32_tdata[29];
        end
        1:
        begin
//          rSFirstDWBE <= s32_tdata[3:0];
        end
        2:
        begin
//          if (!r4DWH)
//            rSAddr <= ({s32_tdata[31:2], 2'b0} & ~ADDR_MASK) | ADDR_BASE;
        end
        3:
        begin
//          if (r4DWH)
//            rSAddr <= ({s32_tdata[31:2], 2'b0} & ~ADDR_MASK) | ADDR_BASE;
        end
      endcase
    end
  end
  
  axis_quarter_width #(
    .DWIDTH  (128),
    .KWIDTH  (4))
  quarter_conv_wr(
    .clk        (CLK),
    .rst        (RST),
      
    .s_tvalid   (S_TVALID  ),
    .s_tready   (S_TREADY  ),
    .s_tdata    (S_TDATA   ),
    .s_tkeep    (S_TSTRB   ),
    .s_tlast    (S_TLAST   ),

    .m_tvalid   (s32_tvalid  ),
    .m_tready   (s32_tready  ),
    .m_tdata    (s32_tdata   ),
    .m_tkeep    (            ),
    .m_tlast    (s32_tlast   )
  );
  
endmodule

module MasterBridgeRd(
  input           CLK,
  input           RST,
  
  input           S_TVALID,
  output          S_TREADY,
  input   [127:0] S_TDATA,
  input   [3:0]   S_TSTRB,
  input           S_TLAST,
  output          M_TVALID,
  input           M_TREADY,
  output  [127:0] M_TDATA,
  output  [3:0]   M_TSTRB,
  output          M_TLAST,
  
  output  [31:0]  M_ARADDR,
  output          M_ARVALID,
  input           M_ARREADY,
  input   [31:0]  M_RDATA,
  input   [1:0]   M_RRESP,
  input           M_RVALID,
  output          M_RREADY
  );

  wire m32_tvalid = 1'b0;
  wire m32_tready;
  wire [31:0] m32_tdata;
  wire m32_tlast;
  assign S_TREADY = 1'b1;
  
  axis_quad_width #(
    .DWIDTH  (32),
    .KWIDTH  (1))
  quad_conv(
    .clk        (CLK),
    .rst        (RST),
      
    .s_tvalid   (m32_tvalid  ),
    .s_tready   (m32_tready  ),
    .s_tdata    (m32_tdata   ),
    .s_tkeep    (1'b1        ),
    .s_tlast    (m32_tlast   ),

    .m_tvalid   (M_TVALID  ),
    .m_tready   (M_TREADY  ),
    .m_tdata    (M_TDATA   ),
    .m_tkeep    (M_TSTRB   ),
    .m_tlast    (M_TLAST   )
  );  
endmodule
